home *** CD-ROM | disk | FTP | other *** search
- #include <Icons.h>
- #include <Resources.h>
- #include <Gestalt.h>
- #include <Sound.h>
- #include <NumberFormatting.h>
-
-
- /*
- ShowInitIcon.c
- ShowINIT compatible routine that shows 'iclx' and 'icns' icons.
- For use by all INITs in System 7.0 and beyond.
- Requires OS 7.0 and up.
-
- 4/7/99
- Modified by Bruce Partridge to handle Icon Services icns resources.
- Also fixed for PowerPC data alignment, and removed support for
- pre Color Quickdraw systems. Now runs either as 68K or PowerPC.
- Send comments/bugs to: Bruce Partridge at <bpart1@aol.com> or <halfhill@kagi.com>
-
-
- This code was written or modified by Paul Mercer, Darin Adler, Paul Snively,
- Steve Capps, Patrick C. Beard, Peter N Lewis, François Pottier, and Jim W Walker.
-
- This code is in the public domain.
-
- Instructions for use:
-
- ••• You must include IconServicesLib to compile this as PowerPC code
- ••• BE SURE TO WEAK LINK THE LIBRARY or you will get an endless and
- ••• baffling series of crashes when Icon Services is not present
- ••• ie OS < 8.5 .
-
- • Create a family of icons with ResEdit 2.1 or later. This will
- include 'ICN#', 'icl4', & 'icl8' icons, all with the
- same resource ID.
- • Optionally create an icns with the same resource ID for use with
- OS 8.5 and up. If your INIT is going to display an icon on OS
- < 8.5 you must supply the icon family as well.
-
- To use within a larger INIT project:
- • #define SEPARATE_CODE 0 below.
- • Call ShowInitIcon( id, adv ) with the resource id of
- the family that you used. The Boolean parameter adv
- indicates whether you want the next use of ShowInitIcon
- to advance to a new position. Normally you pass TRUE,
- but you can get an animated-icon effect by passing FALSE
- all except the last time you call ShowInitIcon.
-
- To use as a separate code resource:
- • #define SEPARATE_CODE 1 below.
- • Set the project type to code resource, set the code type
- and resource ID (I use type 'Code', ID -4048 for cdevs),
- compile and merge into your INIT or cdev file.
- Set the resource type to Locked, so you won't have
- to call HLock when you use it.
- • In your main INIT code, call ShowInitIcon like so:
- pascal void (*ShowInitIcon)( short resid, Boolean adv );
- Handle show_init;
-
- show_init = GetResource( 'Code', -4048 );
- ShowInitIcon = (pascal void (*)(short, Boolean))
- StripAddress( *show_init );
- ShowInitIcon( iconID, advance );
- */
-
- #define SEPARATE_CODE 0
-
-
- #if SEPARATE_CODE
- #define ShowInitIcon main
- #endif
-
- #ifndef nil
- #define nil ((void*)0L)
- #endif
-
- #ifndef topLeft
- #define topLeft(r) ((Point*)&r)[0])
- #endif
- #ifndef botRight
- #define botRight(r) ((Point*)&r)[1])
- #endif
-
- // Alignment here must be 68K, or screenbits.bounds address will be off by
- // padding and GetIconRect will return incorrect values. BP
- #pragma options align=mac68k
- typedef struct myQDGlobals {
- char privates[76];
- long randSeed;
- BitMap screenBits;
- Cursor arrow;
- Pattern dkGray;
- Pattern ltGray;
- Pattern gray;
- Pattern black;
- Pattern white;
- GrafPtr thePort;
- long end;
- } myQDGlobals;
- #pragma options align=reset
-
- /* prototypes */
- pascal void ShowInitIcon(short iconId, Boolean advance);
- static void Next_position( void );
- static void GetIconRect( register Rect* iconRect, Rect *screen_rect );
- OSErr GetSelfFSSpec(FSSpec* theFSSpec);
-
- /*
- //-------------------------------------
- main(void) // For testing purposes only
- {
- int iconId = 128;
- unsigned long finalTick;
-
- ShowInitIcon(iconId,true);
- Delay(200,&finalTick);
-
- return (0);
- }
- //-------------------------------------
- */
-
- /* this is where it all happens. */
- pascal void ShowInitIcon( short iconId, Boolean advance)
- {
- long oldA5;
- myQDGlobals qd; /* our QD globals. */
- CGrafPort gp; /* our grafport. */
- Rect icon_rect;
- OSErr theErr;
- FSSpec theFSSpec;
- IconRef iconRef;
- long gestaltval;
- OSType fakecreator = 'MMac'; // anything will do here
- OSType faketype = 'OS85'; // for Icon Services calls
-
- // Do we have Color QuickDraw etc ?
- Gestalt(gestaltSystemVersion,&gestaltval);
- if(gestaltval < 0x700)
- return;
-
- /* get a value for A5, a structure that mirrors qd globals. */
- oldA5 = SetA5((long)&qd.end);
- InitGraf(&qd.thePort);
-
- GetIconRect( &icon_rect, &(qd.screenBits.bounds) );
- OpenCPort(&gp);
-
- // test for Icon Services icns handling
- Gestalt(gestaltIconUtilitiesAttr,&gestaltval);
- if(gestaltval & gestaltIconUtilitiesHasIconServices)
- {
- // Icon Services will preferentially load icns over iclx of the same ID
- // If there's no icns, it'll load the iclx
- theErr = GetSelfFSSpec(&theFSSpec);
- if(theErr == noErr)
- theErr = RegisterIconRefFromResource (fakecreator,faketype,&theFSSpec,iconId,&iconRef);
- if(theErr == noErr)
- {
- theErr = PlotIconRef(&icon_rect,kAlignAbsoluteCenter,nil,kIconServicesNormalUsageFlag,iconRef);
- theErr = UnregisterIconRef (fakecreator,faketype);
- }
- }
- else
- theErr = PlotIconID( &icon_rect, atNone, ttNone, iconId );
- CloseCPort(&gp);
-
- if (advance)
- Next_position(); /* JWW */
-
- SetA5(oldA5);
- }
-
- /*
- ShowInit's information is nestled at the tail end of CurApName.
- It consists of a short which encodes the next horizontal offset,
- and another short which is that value checksummed with the function below.
- */
-
- #define CurApName_LM 0x910
- #define ShowINITTable ((unsigned short*)(CurApName_LM + 32 - 4))
- #define CheckSumConst 0x1021 /* magic value to check-sum with. */
-
- #define InitialXPosition 8 /* initial horizontal offset. */
- #define YOffset 40 /* constant from bottom to place the icon. */
- #define XOffset 40 /* amount to change it by. */
- #define ICON_WIDTH 32
- #define kDefaultRes 0x00480000 /* Default resolution is 72 DPI; Fixed type */
-
- /* CheckSum() computes the magic value to determine if ShowInit's have run already. */
-
- static short CheckSum(register unsigned short x)
- {
- if (x & 0x8000) /* high bit set */
- return((x << 1) ^ CheckSumConst ^ 0x01);
- else
- return ((x << 1) ^ CheckSumConst);
- }
-
- /*
- GetIconRect() generates an appropriate rectangle to display the
- next INIT's icon in.
- It is also responsible for updating the horizontal
- position in low memory. This is a departure from
- the original ShowInit code, which updates low
- memory AFTER displaying the icon. -- changed by JWW
- This code won't generate an icon position until it is certain that the icon can be loaded,
- so the same behaviour occurs.
-
- This routine also generates a rectangle which is guaranteed to be onscreen. It
- does this by taking the horizontal offset modulo the screen width to generate
- the horizontal position of the icon, and the offset divided by the screen
- width to generate the proper row.
- */
-
- static void GetIconRect(register Rect* iconRect, Rect *screen_rect )
- {
- register short screenWidth;
- screenWidth = screen_rect->right - screen_rect->left;
- screenWidth -= screenWidth % XOffset;
- /* if we are the first INIT to run we need to initialize the horizontal value. */
- if (CheckSum(ShowINITTable[0]) != ShowINITTable[1])
- ShowINITTable[0] = InitialXPosition;
-
- /* compute top left of icon's rect. */
- iconRect->left = (ShowINITTable[0] % screenWidth);
- iconRect->top = screen_rect->bottom -
- YOffset * (1 + (ShowINITTable[0] / screenWidth));
- iconRect->right = iconRect->left + 32;
- iconRect->bottom = iconRect->top + 32;
-
- }
-
- /*
- JWW: In Beard's original version, this was done at the end of
- GetIconRect. That caused incorrect behavior when IconWrap 1.2 was
- used to wrap icons. Namely, if an INIT using that version of
- ShowIconFamily was the first in a row, then the second icon in that
- row would land on top of it.
- */
- static void Next_position( void )
- {
- /* advance the position for the next icon. */
- ShowINITTable[0] += XOffset;
-
- /* recompute the checksum. */
- ShowINITTable[1] = CheckSum(ShowINITTable[0]);
- }
-
-
- OSErr GetSelfFSSpec(FSSpec* theFSSpec)
- {
- OSErr theErr;
- Str255 procname;
- FCBPBRec fcbPB;
- // The FSSpec is needed to get an IconRef with Icon Services
- // Process Manager isn't loaded yet so use PB calls BP 4/99
- fcbPB.ioNamePtr = procname;
- fcbPB.ioVRefNum = 0;
- fcbPB.ioRefNum = CurResFile();
- fcbPB.ioFCBIndx = 0;
- theErr = PBGetFCBInfoSync(&fcbPB);
-
- if(theErr == noErr)
- theErr = FSMakeFSSpec(fcbPB.ioVRefNum,fcbPB.ioFCBParID,procname,theFSSpec);
- return theErr;
- }
-
-